package cn.edu.xmu.oomall.aftersales.service;

import cn.edu.xmu.oomall.aftersales.dao.AfterSaleDao;
import cn.edu.xmu.oomall.aftersales.microservice.*;
import cn.edu.xmu.oomall.aftersales.microservice.vo.*;
import cn.edu.xmu.oomall.aftersales.model.bo.AfterSale;
import cn.edu.xmu.oomall.aftersales.model.po.AftersaleServicePo;
import cn.edu.xmu.oomall.aftersales.model.vo.*;
import cn.edu.xmu.oomall.core.util.Common;
import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.privilegegateway.annotation.util.InternalReturnObject;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static cn.edu.xmu.privilegegateway.annotation.util.Common.*;

/**
 * @author Jiawei Zheng
 * @author zyu
 * @date 2021-12-11
 */
@Service
public class AfterSaleService {

    @Autowired
    private AfterSaleDao afterSaleDao;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private FreightService freightService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsService goodsService;

    @Value("${oomall.aftersales.platformId}")
    private Integer platformId;

    /**
     * 获取售后单所有状态
     * @return
     */
    public ReturnObject getAllAdvanceSaleStates() {
        List<AfterSaleStateRetVo> retVoList = new ArrayList<>();
        for (AfterSale.AfterSaleState state : AfterSale.AfterSaleState.values()) {
            AfterSaleStateRetVo stateRetVo = new AfterSaleStateRetVo(state.getCode(), state.getDescription());
            retVoList.add(stateRetVo);
        }
        return new ReturnObject(retVoList);
    }

    /**
     * 买家提交售后单
     * @param userId
     * @param userName
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject createAfterSale(Long userId, String userName, Long id, CreateAfterSaleVo vo){
        AfterSale bo = cloneVo(vo, AfterSale.class);
        bo.setState(AfterSale.AfterSaleState.NEW);
        bo.setOrderItemId(id);
        bo.setCustomerId(userId);
        InternalReturnObject<OrderItemRetVo> internalReturnObject = orderService.getOrderItemInfoById(id);
        if(internalReturnObject.getData()==null){
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,internalReturnObject.getErrmsg());
        }
        bo.setShopId(internalReturnObject.getData().getShopId());
        bo.setBeDeleted((byte)0);
        bo.setServiceSn(genSeqNum(platformId));
        setPoCreatedFields(bo, userId, userName);
        ReturnObject returnObject = afterSaleDao.insertAfterSale(bo);
        if(returnObject.getData()==null){
            return returnObject;
        }
        return new ReturnObject(cloneVo(returnObject.getData(), SimpleAfterSaleRetVo.class));
    }

    /**
     * 买家修改售后单信息
     * @param userId
     * @param userName
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject changeAfterSale(Long userId, String userName, Long id, ModifyAfterSaleVo vo){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleByIdAndUserId(userId, id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        //状态如果不为新建或待买家发货，不能修改
        if(!po.getState().equals(AfterSale.AfterSaleState.NEW.getCode())&&!po.getState().equals(AfterSale.AfterSaleState.WAIT_CUSTOMER_POST.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        AfterSale bo = cloneVo(vo, AfterSale.class);
        bo.setId(id);
        bo.setState(AfterSale.AfterSaleState.NEW);
        setPoModifiedFields(bo,userId,userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     * 买家取消售后单和逻辑删除售后单
     * @param userId
     * @param userName
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject deleteAfterSale(Long userId, String userName, Long id){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleByIdAndUserId(userId, id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        AfterSale bo = new AfterSale();
        setPoModifiedFields(bo, userId ,userName);
        //售后单完成前，状态为新建0或待买家发货1，取消售后单
        if(po.getState().equals(AfterSale.AfterSaleState.NEW.getCode())||po.getState().equals(AfterSale.AfterSaleState.WAIT_CUSTOMER_POST.getCode())){
            bo.setState(AfterSale.AfterSaleState.CANCELED);
            return afterSaleDao.updateAfterSale(bo);
        }
        //售后单已完成，状态为已结束6或已取消7，逻辑删除
        else if(po.getState().equals(AfterSale.AfterSaleState.FINISHED.getCode())||po.getState().equals(AfterSale.AfterSaleState.CANCELED.getCode())){
            bo.setBeDeleted((byte)1);
            return afterSaleDao.updateAfterSale(bo);
        }
        else{
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
    }

    /**
     * 买家填写售后运单信息
     * @param userId
     * @param userName
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject sendbackAfterSale(Long userId, String userName, Long id, SendBackAfterSaleVo vo){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleByIdAndUserId(userId, id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        //售后单状态为等待买家发货才可以填写售后运单信息
        if(!po.getState().equals(AfterSale.AfterSaleState.WAIT_CUSTOMER_POST.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        AfterSale bo = cloneVo(vo, AfterSale.class);
        bo.setState(AfterSale.AfterSaleState.CUSTOMER_POSTED);
        setPoModifiedFields(bo, userId, userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     * 买家确认售后单结束
     * @param userId
     * @param userName
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject confirmAfterSale(Long userId, String userName, Long id){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleByIdAndUserId(userId, id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        //售后单状态为店家已发货才可以确认售后单结束
        if(!po.getState().equals(AfterSale.AfterSaleState.SHOP_POSTED.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        AfterSale bo = new AfterSale();
        bo.setState(AfterSale.AfterSaleState.FINISHED);
        setPoModifiedFields(bo, userId, userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     * 管理员同意或不同意售后请求
     * @param userId
     * @param userName
     * @param shopId
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject acceptAfterSale(Long userId, String userName, Long shopId, Long id, AcceptAfterSaleVo vo){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleById(id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        //售后单的shopId与传入的shopId对不上
        if(!po.getShopId().equals(shopId)){
            return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
        }
        //售后单状态为新建才可以同意或不同意售后
        if(!po.getState().equals(AfterSale.AfterSaleState.NEW.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        AfterSale bo = cloneVo(vo, AfterSale.class);
        //如果同意
        if(vo.getConfirm().equals(true)){
            bo.setState(AfterSale.AfterSaleState.WAIT_CUSTOMER_POST);
        }
        else{
            bo.setState(AfterSale.AfterSaleState.CANCELED);
        }
        setPoModifiedFields(bo, userId, userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     *
     * 店家验收买家收到的退（换）货
     * @param userId
     * @param userName
     * @param shopId
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject receiveAfterSale(Long userId, String userName, Long shopId, Long id, ReceiveAfterSaleVo vo){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleById(id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        if(!po.getShopId().equals(shopId)){
            return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
        }
        //售后单状态为买家已发货2才可以验收
        if(!po.getState().equals(AfterSale.AfterSaleState.CUSTOMER_POSTED.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        Byte type = po.getType();
        AfterSale bo = cloneVo(vo, AfterSale.class);
        bo.setConclusion(vo.getConclusion());
        //换货，需要创建新的售后订单
        if(type.equals((byte)0)){
            OrderInfoVo orderInfoVo = new OrderInfoVo();
            Long orderItemId = po.getOrderItemId();
            SimpleOrderItemVo simpleOrderItemVo = new SimpleOrderItemVo();
            //先用orderItemId查orderItem，拿到productId
            InternalReturnObject<OrderItemRetVo> getOrderItemReturnObject = orderService.getOrderItemInfoById(orderItemId);
            if(getOrderItemReturnObject.getData()==null){
                return new ReturnObject(getOrderItemReturnObject);
            }
            Long productId = getOrderItemReturnObject.getData().getProductId();
            //拿productId去查product，拿到onsaleId
            InternalReturnObject<ProductRetVo> getProductReturnObject = goodsService.getShopProductDetails(shopId, productId, userId, userName);
            if(getProductReturnObject.getData()==null){
                return new ReturnObject(getProductReturnObject);
            }
            Long onsaleId = getProductReturnObject.getData().getOnSaleId();
            simpleOrderItemVo.setProductId(productId);
            simpleOrderItemVo.setOnsaleId(onsaleId);
            simpleOrderItemVo.setQuantity(po.getQuantity());
            orderInfoVo = cloneVo(po, OrderInfoVo.class);
            orderInfoVo.setOrderItems(simpleOrderItemVo);
            orderInfoVo.setAddress(po.getDetail());
            orderInfoVo.setMessage(vo.getConclusion());
            //创建订单
            InternalReturnObject createOrderReturnObject = orderService.createOrder(shopId, orderInfoVo);
            if(createOrderReturnObject.getData()==null){
                return new ReturnObject(createOrderReturnObject);
            }
            bo.setPrice(0L);
            bo.setState(AfterSale.AfterSaleState.SHOP_POSTED);
        }
        //维修
        else if(type.equals((byte)2)){
            bo.setState(AfterSale.AfterSaleState.WAIT_PAY);
            //等待前端调用支付接口，可以用rocketmqConsumer接受退款成功通知
        }
        //退货
        else{
            bo.setState(AfterSale.AfterSaleState.WAIT_REFUND);
            //调用退款接口
            InternalReturnObject refundRetuenObject = paymentService.refund(po.getServiceSn(), po.getQuantity(), (byte)2, vo.getConclusion());
            if(refundRetuenObject.getData()==null){
                return new ReturnObject(refundRetuenObject);
            }
            //rockemqConsumer等待退款成功通知
        }
        setPoModifiedFields(bo, userId, userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     * 店家发货
     * @param userId
     * @param userName
     * @param shopId
     * @param id
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ReturnObject deliverAfterSale(Long userId, String userName, Long shopId, Long id, DeliverAfterSaleVo vo){
        ReturnObject<AftersaleServicePo> returnObject = afterSaleDao.selectAfterSaleById(id);
        if(returnObject.getData()==null){
            return returnObject;
        }
        AftersaleServicePo po = returnObject.getData();
        if(!po.getShopId().equals(shopId)){
            return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
        }
        //售后单状态为待店家发货4才可以填写寄回运单
        if(!po.getState().equals(AfterSale.AfterSaleState.WAIT_SHOP_POST.getCode())){
            return new ReturnObject(ReturnNo.STATENOTALLOW);
        }
        AfterSale bo = cloneVo(vo, AfterSale.class);
        bo.setState(AfterSale.AfterSaleState.SHOP_POSTED);
        setPoModifiedFields(bo, userId, userName);
        return afterSaleDao.updateAfterSale(bo);
    }

    /**
     * 顾客根据id查询自己的售后单
     * @param userId
     * @param aftersaleId
     * @return
     */
    @Transactional(readOnly = true)
    public ReturnObject customerSelectAfterSaleByid(Long userId,Long aftersaleId) {
        ReturnObject returnObject=afterSaleDao.selectAfterSaleById(aftersaleId);
        if(returnObject.getData()!=null) {
            AftersaleServicePo po=(AftersaleServicePo) returnObject.getData();
            if(!po.getCustomerId().equals(userId)) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
            }
            AfterSaleRetVo vo=cloneVo(po,AfterSaleRetVo.class);
            ReturnObject customerInfo=customerService.getCustomerInfo(userId);
            if(customerInfo.getData()==null) {
                return new ReturnObject(customerInfo);
            }
            CustomerRetVo customerRetVo=(CustomerRetVo) customerInfo.getData();
            SimpleInfoVo customer=cloneVo(customerRetVo,SimpleInfoVo.class);
            vo.setCustomer(customer);
            InternalReturnObject regionInfo=freightService.getRegionInfo(po.getRegionId());
            if(regionInfo.getData()==null) {
                return new ReturnObject(regionInfo);
            }
            SimpleRegionRetVo simpleRegionRetVo=(SimpleRegionRetVo) regionInfo.getData();
            SimpleInfoVo region=cloneVo(simpleRegionRetVo,SimpleInfoVo.class);
            vo.setRegion(region);
            return new ReturnObject(vo);
        }
        else {
                return returnObject;
        }
    }

    /**
     * 顾客条件查询自己的售后单
     * @param customerId
     * @param state
     * @param beginTime
     * @param endTime
     * @param page
     * @param pageSize
     * @return
     */
    @Transactional(readOnly = true)
    public ReturnObject customerSelectAfterSale(Long customerId,Byte state, LocalDateTime beginTime,LocalDateTime endTime,Integer page,Integer pageSize) {
        AfterSale afterSale=new AfterSale();
        afterSale.setCustomerId(customerId);
        afterSale.setState(AfterSale.AfterSaleState.getTypeByCode(state));
        ReturnObject returnObject=afterSaleDao.selectAfterSaleByCondition(afterSale,beginTime,endTime,page,pageSize);
        if(returnObject.getData()!=null) {
            List<AftersaleServicePo> pos=(List<AftersaleServicePo>) returnObject.getData();
            PageInfo pageInfo=new PageInfo(pos);
            List<SimpleAfterSaleRetVo> voList=new ArrayList<>();
            ReturnObject returnObject1=new ReturnObject(pageInfo);
            return Common.getPageRetVo(returnObject1,SimpleAfterSaleRetVo.class);
        }
        else {
                return returnObject;
        }
    }

    /**
     * 管理员条件查询售后单
     * @param shopId
     * @param state
     * @param type
     * @param beginTime
     * @param endTime
     * @param page
     * @param pageSize
     * @return
     */
    @Transactional(readOnly = true)
    public ReturnObject adminSelectAfterSale(Long shopId,Byte state,Byte type,LocalDateTime beginTime,LocalDateTime endTime,Integer page,Integer pageSize) {
        AfterSale afterSale=new AfterSale();
        afterSale.setType(type);
        afterSale.setShopId(shopId);
        afterSale.setState(AfterSale.AfterSaleState.getTypeByCode(state));
        ReturnObject returnObject=afterSaleDao.selectAfterSaleByCondition(afterSale,beginTime,endTime,page,pageSize);
        if(returnObject.getData()!=null) {
            List<AftersaleServicePo> pos=(List<AftersaleServicePo>) returnObject.getData();
            PageInfo pageInfo=new PageInfo(pos);
            ReturnObject returnObject1=new ReturnObject(pageInfo);
            return Common.getPageRetVo(returnObject1,SimpleAfterSaleRetVo.class);
        }
        else {
                return returnObject;
        }
    }

    /**
     * 管理员通过ID查询售后单
     * @param shopId
     * @param aftersaleId
     * @return
     */
    @Transactional(readOnly = true)
    public ReturnObject adminSelectAfterSaleByid(Long shopId,Long aftersaleId) {
        ReturnObject returnObject = afterSaleDao.selectAfterSaleById(aftersaleId);
        if (returnObject.getData() != null) {
            AftersaleServicePo po = (AftersaleServicePo) returnObject.getData();
            if (!po.getShopId().equals(shopId) && (shopId!=0L)) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
            } else {
                FullAfterSaleRetVo vo = cloneVo(po, FullAfterSaleRetVo.class);
                ReturnObject customerInfo = customerService.getCustomerInfo(po.getCustomerId());
                if (customerInfo.getData() != null) {
                    CustomerRetVo customerRetVo = (CustomerRetVo) customerInfo.getData();
                    SimpleInfoVo customer = cloneVo(customerRetVo, SimpleInfoVo.class);
                    vo.setCustomer(customer);
                }
                InternalReturnObject regionInfo = freightService.getRegionInfo(po.getRegionId());
                if (regionInfo.getData() != null) {
                    SimpleRegionRetVo simpleRegionRetVo = (SimpleRegionRetVo) regionInfo.getData();
                    SimpleInfoVo region = cloneVo(simpleRegionRetVo, SimpleInfoVo.class);
                    vo.setRegion(region);
                }
                return new ReturnObject(vo);
            }

        } else {
                return returnObject;
        }
    }

    /**
     * 获取售后支付单
     * @param userId
     * @param aftersaleId
     * @return
     */
    @Transactional(readOnly = true)
    public ReturnObject getAfterSalePayments(Long userId,Long aftersaleId) {
        //判断是否为用户的售后单
        ReturnObject returnAfterSale=afterSaleDao.selectAfterSaleById(aftersaleId);
        if(returnAfterSale.getData()!=null) {
            AftersaleServicePo po=(AftersaleServicePo) returnAfterSale.getData();
            if(!po.getCustomerId().equals(userId)) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE);
            }
            InternalReturnObject returnObject=paymentService.getPaymentByDocumentId(po.getServiceSn());
            return new ReturnObject(returnObject);
        }
        return returnAfterSale;
    }

    public InternalReturnObject<AfterSaleRetVo> getAfterSaleBySn(String serviceSn) {
        ReturnObject returnObject = afterSaleDao.selectAfterSaleBySn(serviceSn);
        if (returnObject.getData() != null) {
            AfterSale afterSale = (AfterSale)returnObject.getData();
            return new InternalReturnObject<>(cloneVo(afterSale, AfterSaleRetVo.class));
        }
        return new InternalReturnObject<>(returnObject.getCode().getCode(), returnObject.getErrmsg());
    }
}
